/**
 * Copyright phonemap.com
 *
 * Licensed under the phonemap.com License, Version 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.phonemap.com/licenses/LICENSE-1.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.phonemap;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;

import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.search.GeoPoint;
import com.phonemap.common.AppConstant;
import com.phonemap.common.Util;
import com.phonemap.dto.FriendDTO;
import com.phonemap.dto.FriendList;
import com.phonemap.models.User;

/**
 * The Class IndexServlet.
 */
@SuppressWarnings("serial")
public class IndexServlet extends BaseServlet {

	/** The Constant logger. */
	private final Logger logger = Logger.getLogger(PositionServlet.class
			.getCanonicalName());

	/**
	 * Get the requested position entities in JSON format.
	 * 
	 * @param req
	 *            the req
	 * @param resp
	 *            the resp
	 * @throws ServletException
	 *             the servlet exception
	 * @throws IOException
	 *             Signals that an I/O exception has occurred.
	 */
	protected final void doGet(final HttpServletRequest req,
			final HttpServletResponse resp) throws ServletException,
			IOException {

		// FIXME: Fix exception
		super.doGet(req, resp);
		logger.log(Level.INFO, "Obtaining Position listing");
		String userId = req.getParameter("userId");
		String action = req.getParameter("action");
		PrintWriter out = resp.getWriter();

		List<Entity> entities = new ArrayList<Entity>();

		if (action.equalsIgnoreCase("getFriends")) {
			if (userId != null && userId != "") {
				Entity user = User.getUser(Long.parseLong(userId));
				int idx = 0;
				if (user != null) {
					entities.add(idx++, user);
				}
				// 1. get received JSON data from request
				BufferedReader br = new BufferedReader(new InputStreamReader(
						req.getInputStream()));
				String json = "";
				if (br != null) {
					json = br.readLine();
				}

				FriendList article = new FriendList();
				try {
					ObjectMapper mapper = new ObjectMapper();
					// 3. Convert received JSON to Article
					article = mapper.readValue(json, FriendList.class);
					Entity friend = null;
					for (FriendDTO friendDTO : article.getData()) {
						friend = User.getUser(friendDTO.getId());
						if (friend != null) {
							if (friend.getProperty(User.LOCATED_TIME_FIELD) != null) {
								entities.add(idx++, friend);
							}
						} else {
							User.insertUser(friendDTO.getId(),
									friendDTO.getName());
						}
					}
				} catch (JsonGenerationException e) {
					e.printStackTrace();
				} catch (JsonMappingException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
				out.println(Util.writeJSON(entities, AppConstant.ENTITY_USER));
			}
		} else if (action.equalsIgnoreCase("searchusers")) {
			double latitude = Double.parseDouble(req.getParameter("latitude"));
			double longitude =  Double.parseDouble(req.getParameter("longitude"));
			int distance = Integer.parseInt(req.getParameter("distance"));
			int offset = Integer.parseInt(req.getParameter("offset"));
			try {
				entities = User.getUsers(new GeoPoint(latitude, longitude), distance, offset);
				out.println(Util.writeJSON(entities, AppConstant.ENTITY_USER));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return;
	}

	/**
	 * Insert the new position.
	 * 
	 * @param req
	 *            the req
	 * @param resp
	 *            the resp
	 * @throws ServletException
	 *             the servlet exception
	 * @throws IOException
	 *             Signals that an I/O exception has occurred.
	 */
	protected final void doPut(final HttpServletRequest req,
			final HttpServletResponse resp) throws ServletException,
			IOException {
	}

	/**
	 * Redirect the call to doDelete or doPut method.
	 * 
	 * @param req
	 *            the req
	 * @param resp
	 *            the resp
	 * @throws ServletException
	 *             the servlet exception
	 * @throws IOException
	 *             Signals that an I/O exception has occurred.
	 */
	protected final void doPost(final HttpServletRequest req,
			final HttpServletResponse resp) throws ServletException,
			IOException {
		String action = req.getParameter("action");
		resp.setContentType("text/html; charset=UTF-8");
		PrintWriter out = resp.getWriter();

		List<Entity> entities = new ArrayList<Entity>();

		if (action.equalsIgnoreCase("getFriends")) {
			// get received JSON data from request
			BufferedReader br = new BufferedReader(new InputStreamReader(
					req.getInputStream(), AppConstant.UTF_8));
			String json = "";
			if (br != null) {
				json = br.readLine();
			}

			FriendList article = new FriendList();
			try {
				ObjectMapper mapper = new ObjectMapper();
				// Convert received JSON to Article
				article = mapper.readValue(json, FriendList.class);
				Entity friend = null;
				for (FriendDTO friendDTO : article.getData()) {
					friend = User.getUser(friendDTO.getId());
					if (friend != null) {
						if (friend.getProperty(User.LOCATED_TIME_FIELD) != null) {
							entities.add(friend);
						}
					} else {
						User.insertUser(friendDTO.getId(), friendDTO.getName());
					}
				}

			} catch (JsonGenerationException e) {
				e.printStackTrace();
			} catch (JsonMappingException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		} else if (action.equalsIgnoreCase("searchusers")) {
			double latitude = Double.parseDouble(req.getParameter("latitude"));
			double longitude =  Double.parseDouble(req.getParameter("longitude"));
			int distance = Integer.parseInt(req.getParameter("distance"));
			int offset = Integer.parseInt(req.getParameter("offset"));
			try {
				entities = User.getUsers(new GeoPoint(latitude, longitude), distance, offset);
				out.println(Util.writeJSON(entities, AppConstant.ENTITY_USER));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		out.println(Util.writeJSON(entities, AppConstant.ENTITY_USER));
	}

}
